package com.itaming.lycheeframework.support.datetime;

import com.itaming.lycheeframework.support.utils.LocaleUtil;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 线程安全的{@link Date}格式化器工厂
 *
 * @author A.Ming
 */
public class ThreadSafeDateFormatFactory {

    /**
     * {@link DateFormat}缓存
     */
    private static final Map<String, ThreadLocal<DateFormat>> cache = new ConcurrentHashMap<>();

    /**
     * 获取线程安全的{@link DateFormat}实例
     *
     * @param pattern 格式
     * @return {@link DateFormat}实例
     */
    public static ThreadLocal<DateFormat> getDateFormat(String pattern) {
        return getDateFormat(pattern, LocaleUtil.getDefault());
    }

    /**
     * 获取线程安全的{@link DateFormat}实例
     *
     * @param pattern 格式
     * @param locale  语言环境
     * @return {@link DateFormat}实例
     */
    public static ThreadLocal<DateFormat> getDateFormat(String pattern, Locale locale) {
        return getDateFormat(pattern, locale, null);
    }

    /**
     * 获取线程安全的{@link DateFormat}实例
     *
     * @param pattern  格式
     * @param locale   语言环境
     * @param timeZone 时区
     * @return {@link DateFormat}实例
     */
    public static ThreadLocal<DateFormat> getDateFormat(String pattern, Locale locale, TimeZone timeZone) {
        ThreadLocal<DateFormat> dateFormatThreadLocal = cache.get(getKey(pattern, locale, timeZone));
        if (dateFormatThreadLocal == null) {
            dateFormatThreadLocal = ThreadLocal.withInitial(() -> createDateFormat(pattern, locale, timeZone));
            cache.put(getKey(pattern, locale, timeZone), dateFormatThreadLocal);
        }
        return dateFormatThreadLocal;
    }

    /**
     * 获取缓存key
     *
     * @param pattern  格式
     * @param locale   语言环境
     * @param timeZone 时区
     * @return 缓存key
     */
    private static String getKey(String pattern, Locale locale, TimeZone timeZone) {
        return pattern + "_" + locale + "_" + timeZone;
    }

    /**
     * 创建{@link DateFormat}实例
     *
     * @param pattern  格式
     * @param locale   语言环境
     * @param timeZone 时区
     * @return {@link DateFormat}实例
     */
    private static DateFormat createDateFormat(String pattern, Locale locale, TimeZone timeZone) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern, locale);
        if (timeZone != null) {
            simpleDateFormat.setTimeZone(timeZone);
        }
        return simpleDateFormat;
    }

}
